package be.pluyckx.batteryprogress.database;

import android.content.Context;
import android.util.Log;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import be.pluyckx.batteryprogress.application.Constants;
import be.pluyckx.batteryprogress.data.history.BatteryHistory;
import be.pluyckx.batteryprogress.data.history.BatteryLevel;

/**
 * Created by Philip Luyckx on 3/08/13.
 */
public class BatteryLevelFileStorage extends BatteryHistoryDatabase {
  private static final String TAG = "BatteryLevelFileStorage";

  private static final File mFileName = new File(Constants.dataDirectory, "history.dat");
  private boolean mHistoryChanged = false;

  public BatteryLevelFileStorage(Context context, BatteryHistory batteryHistory) {
    super(context, batteryHistory);
  }

  @Override
  public synchronized void read() throws IOException {
    getBatteryHistory().removeObserver(this);
    getBatteryHistory().clear(true);

    DataInputStream dis = null;
    try {
      if (mFileName.exists()) {
        dis = new DataInputStream(new FileInputStream(mFileName));
        int size = dis.readInt();
        if (size > 0) {
          Collection<BatteryLevel> levels = new ArrayList<BatteryLevel>(size);
          for (int i = 0; i < size; i++) {
            levels.add(new BatteryLevel(dis));
          }

          getBatteryHistory().add(levels);
        }
      }
    } catch (IOException e) {
      mFileName.delete();
      throw e;
    } finally {
      if (dis != null) {
        try {
          dis.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }

      getBatteryHistory().addObserver(this);
    }
  }

  @Override
  public void clear() throws IOException {
    if (mFileName.exists()) {
      synchronized (this) {
        if (mFileName.exists()) {
          mFileName.delete();
        }
      }
    }
  }

  @Override
  protected void onItemAdded(int start, int end) {
    synchronized (this) {
      mHistoryChanged = false;
      DataOutputStream dos = null;
      try {
        dos = new DataOutputStream(new FileOutputStream(mFileName));
        int size = Integer.SIZE / 8;

        dos.writeInt(getBatteryHistory().size());
        int index = 0;
        BatteryHistory history = BatteryHistory.getHistory();
        while (index < history.size() && !mHistoryChanged) {
          BatteryLevel level = history.get(index);
          level.write(dos);
          size += level.streamSize();
          index++;
        }

        Log.d(TAG, "Written " + size + " bytes");
      } catch (IOException ex) {
        ex.printStackTrace();
      } finally {
        if (dos != null) {
          try {
            dos.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  @Override
  protected void onItemRemoved(int start, int end) {
    mHistoryChanged = true;
    onItemAdded(0, 0);
  }

  @Override
  protected void onItemUpdated(int start, int end) {
    mHistoryChanged = true;
    onItemAdded(0, 0);
  }

  public static interface FileWritable {
    public int streamSize();

    public void write(DataOutputStream fc) throws IOException;
  }
}
